package com.dc.bobaoge.project.base.core.util;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.dc.bobaoge.base.entity.message.common.po.MessageAsset;
import com.dc.bobaoge.base.mapper.message.MessageAssetMapper;
import com.dc.bobaoge.common.em.MessageTemplateEnum;
import com.dc.bobaoge.common.util.YearQuarterUtil;
import com.dc.bobaoge.project.base.core.constant.BaseInfoConstant;
import com.dc.bobaoge.project.base.core.now.service.TitleService;
import com.dc.bobaoge.project.base.core.now.service.ZoneService;
import com.dc.bobaoge.project.base.core.old.entity.OldCoreMessage;
import com.dc.bobaoge.project.base.core.old.entity.OldCoreMessageType;
import com.dc.bobaoge.project.base.core.old.mapper.OldCoreAdvertisementMapper;
import com.dc.bobaoge.project.base.core.old.mapper.OldCoreMessageMapper;
import com.dc.bobaoge.project.base.core.old.mapper.OldCoreMessageTypeMapper;
import com.dc.bobaoge.project.base.core.util.model.MessageDetailBaseInfoModel;
import com.dc.bobaoge.project.base.core.util.model.MessageSimpleBaseInfoModel;
import com.own.component.common.exception.BusinessSimpleException;
import com.own.component.common.util.list.ListUtil;
import com.own.component.store.core.Store;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * MessageCommonUtil
 *
 * @author chenxueli
 * @date 2024-01-15 10:57:00
 */
@Slf4j
@Component
public class MessageCommonUtil {

    @Resource
    private Store<String> store;

    @Resource
    private OldCoreMessageTypeMapper oldCoreMessageTypeMapper;
    @Resource
    private OldCoreMessageMapper oldCoreMessageMapper;
    @Resource
    private OldCoreAdvertisementMapper oldCoreAdvertisementMapper;

    @Resource
    private MessageAssetMapper messageAssetMapper;

    @Resource
    private ZoneService zoneService;
    @Resource
    private TitleService titleService;

    /**
     * 获取消息的基础信息
     *
     * @param messageId 消息id
     * @return 消息基础信息
     */
    public MessageSimpleBaseInfoModel getSimple(Long messageId) {
        return getSimple(messageId, oldCoreMessageMapper::selectById);
    }

    /**
     * 获取消息的基础信息
     *
     * @param oldCoreMessage 旧消息信息
     * @return 消息基础信息
     */
    public MessageSimpleBaseInfoModel getSimple(OldCoreMessage oldCoreMessage) {
        return getSimple(oldCoreMessage.getMessageId(), messageId -> oldCoreMessage);
    }

    /**
     * 获取消息的基础信息
     *
     * @param messageId 消息id
     * @param function  获取消息实体的方法
     * @return 消息基础信息
     */
    private MessageSimpleBaseInfoModel getSimple(Long messageId, Function<Long, OldCoreMessage> function) {
        var key = buildSimpleKey(messageId);
        // 去查询缓存信息，如果存在直接返回
        if (store.value().contains(key)) {
            return JSON.parseObject(store.value().get(key), MessageSimpleBaseInfoModel.class);
        }
        var oldCoreMessage = function.apply(messageId);
        var resultModel = new MessageSimpleBaseInfoModel();
        if (oldCoreMessage == null) {
            // 如果消息不存在说明是广告的信息
            var advertisement = oldCoreAdvertisementMapper.selectById(messageId);
            if (oldCoreAdvertisementMapper == null) {
                throw new BusinessSimpleException("信息不存在:" + messageId);
            }
            resultModel.setQuarter(YearQuarterUtil.get(advertisement.getAdvmsgDate()));
            resultModel.setId(advertisement.getAdvmsgId());
            resultModel.setType(MessageTemplateEnum.ADVERTISEMENT.getType());
            resultModel.setUserId(advertisement.getAdvmsgUserId());
        } else {
            // 获取标题id
            var titleId = oldCoreMessage.getMessageType();
            // 获取频道id
            var channelItem = getChannelItem(titleId);
            var channelId = channelItem.getChannelId();
            // 获取模板信息
            var messageTemplate = MessageTemplate.get(channelId);
            resultModel.setQuarter(YearQuarterUtil.get(oldCoreMessage.getMessageDate()));
            resultModel.setId(oldCoreMessage.getMessageId());
            resultModel.setType(messageTemplate.getType());
            resultModel.setUserId(oldCoreMessage.getMessageUserId());
            resultModel.setChannelId(channelId);
            resultModel.setChannelName(channelItem.getChannelName());
            resultModel.setTitleId(titleId.longValue());
        }
        store.value().set(key, JSON.toJSONString(resultModel), 24, TimeUnit.HOURS);
        return resultModel;
    }

    /**
     * 获取消息的详细信息
     *
     * @param messageId 消息id
     * @return 消息详细信息
     */
    public MessageDetailBaseInfoModel getDetail(Long messageId) {
        return getDetail(messageId, oldCoreMessageMapper::selectById);
    }


    /**
     * 获取消息的详细信息
     *
     * @param oldCoreMessage 旧消息信息
     * @return 消息详细信息
     */
    public MessageDetailBaseInfoModel getDetail(OldCoreMessage oldCoreMessage) {
        return getDetail(oldCoreMessage.getMessageId(), messageId -> oldCoreMessage);
    }

    /**
     * 获取消息的详细信息
     *
     * @param messageId 消息id
     * @param function  获取消息实体的方法
     * @return 消息详细信息
     */
    private MessageDetailBaseInfoModel getDetail(Long messageId, Function<Long, OldCoreMessage> function) {
        var key = buildDetailKey(messageId);
        // 去查询缓存信息，如果存在直接返回
        if (store.value().contains(key)) {
            return JSON.parseObject(store.value().get(key), MessageDetailBaseInfoModel.class);
        }
        var oldCoreMessage = function.apply(messageId);
        if (oldCoreMessage == null) {
            throw new BusinessSimpleException("信息不存在:" + messageId);
        }
        // 获取基础信息
        var simple = getSimple(oldCoreMessage);
        var resultModel = new MessageDetailBaseInfoModel(simple);
        var zone = zoneService.getById(oldCoreMessage.getMessageZoneId());
        if (zone != null) {
            resultModel.setZoneId(zone.getId());
            resultModel.setZoneName(zone.getName());
        }
        // 标题名称
        var title = titleService.getById(simple.getTitleId());
        if (title != null) {
            resultModel.setTitleName(title.getName());
        }
        store.value().set(key, JSON.toJSONString(resultModel), 24, TimeUnit.HOURS);
        return resultModel;
    }

    /**
     * 获取频道id
     *
     * @param titleId 标题id
     * @return 频道id
     */
    private ChannelItem getChannelItem(Integer titleId) {
        var tempTitleChannel = TitleChannel.getItemByTitleId(titleId);
        if (tempTitleChannel == null) {
            var item = selectById(titleId);
            if (item == null) {
                return ChannelItem.NONE;
            }
            return new ChannelItem(item.getMsgIsSearch().longValue(), item.getMsgTypeName());
        }
        return tempTitleChannel.getChannel();
    }

    /**
     * 获取消息的类型信息
     *
     * @return 消息类型
     */
    private Map<Integer, OldCoreMessageType> mapMessageType() {
        var list = oldCoreMessageTypeMapper.selectList(null);
        return list.stream().collect(Collectors.toMap(OldCoreMessageType::getMsgTypeId, Function.identity()));
    }

    /**
     * 获取消息的类型信息
     *
     * @return 消息类型
     */
    private OldCoreMessageType selectById(Integer titleId) {
        return oldCoreMessageTypeMapper.selectById(titleId);
    }

    /**
     * 新增媒资信息
     *
     * @param messageId    消息id
     * @param templateType 模板名称
     * @param quarter      季度信息
     * @param oldImageUrls 旧的图片信息
     */
    public void addImageAsset(Long messageId, String templateType, String quarter, String oldImageUrls) {
        if (StringUtils.isBlank(oldImageUrls)) {
            return;
        }
        // 处理通用的其他信息（媒资信息）
        var asset = new MessageAsset();
        asset.setImageUrls(String.join(",", ListUtil.Spilt.to(oldImageUrls, BaseInfoConstant.IMAGE_SPILT)));
        asset.setFkMessageId(messageId);
        asset.setSharding(quarter);
        asset.setType(templateType);
        // 保存信息
        messageAssetMapper.insert(asset);
    }

    /**
     * 处理媒资信息
     *
     * @param messageId    消息id
     * @param templateType 模板名称
     * @param quarter      季度信息
     * @param oldImageUrls 旧的图片信息
     */
    public void updateImageAsset(Long messageId, String templateType, String quarter, String oldImageUrls) {
        // 获取原有的媒资信息
        var wrapper = new LambdaQueryWrapper<MessageAsset>()
                .eq(MessageAsset::getFkMessageId, messageId)
                .eq(MessageAsset::getType, templateType)
                .eq(MessageAsset::getSharding, quarter);
        var asset = messageAssetMapper.selectOne(wrapper);
        if (asset == null) {
            addImageAsset(messageId, templateType, quarter, oldImageUrls);
        } else {
            asset.setImageUrls(String.join(",", ListUtil.Spilt.to(oldImageUrls, BaseInfoConstant.IMAGE_SPILT)));
            var updateWrapper = new LambdaUpdateWrapper<MessageAsset>()
                    .eq(MessageAsset::getFkMessageId, messageId)
                    .eq(MessageAsset::getType, templateType)
                    .eq(MessageAsset::getSharding, quarter);
            asset.setType(null);
            asset.setSharding(null);
            messageAssetMapper.update(asset, updateWrapper);
        }
    }

    /**
     * 构建缓存的key（基础）
     *
     * @param messageId 消息id
     * @return 缓存的key
     */
    private String buildSimpleKey(Long messageId) {
        return "mos:" + messageId;
    }

    /**
     * 构建缓存的key（详细）
     *
     * @param messageId 消息id
     * @return 缓存的key
     */
    private String buildDetailKey(Long messageId) {
        return "mod:" + messageId;
    }

    public static class TitleChannel {

        private static final List<Item> TITLE_CHANNEL_MAP_LIST = new ArrayList<>();
        private static final Map<Integer, Item> TITLE_ID_CHANNEL_ID_MAP = new HashMap<>();

        static {
            TITLE_CHANNEL_MAP_LIST.add(new Item(18, "转让其他", 873693723123388416L, "物品转让"));
            TITLE_CHANNEL_MAP_LIST.add(new Item(21, "找货源", 873693723123388416L, "物品转让"));
            TITLE_CHANNEL_MAP_LIST.add(new Item(44, "求购", 873693723123388416L, "物品转让"));
            TITLE_CHANNEL_MAP_LIST.add(new Item(37, "供应", 873693723123388416L, "物品转让"));

            TITLE_CHANNEL_MAP_LIST.add(new Item(47, "其他需求", 873693724671086592L, "生活配套"));
            TITLE_CHANNEL_MAP_LIST.add(new Item(32, "求助", 873693724671086592L, "生活配套"));

            TITLE_ID_CHANNEL_ID_MAP.putAll(TITLE_CHANNEL_MAP_LIST.stream().collect(Collectors.toMap(Item::getTitleId, Function.identity())));
        }

        /**
         * 根据标题获取频道
         *
         * @param titleId 标题id
         * @return 频道id
         */
        public static Item getItemByTitleId(Integer titleId) {
            return TITLE_ID_CHANNEL_ID_MAP.get(titleId);
        }

        @Data
        public static class Item {

            private Integer titleId;

            private String titleName;

            private ChannelItem channel;

            public Item(Integer titleId, String titleName, Long channelId, String channelName) {
                this.titleId = titleId;
                this.titleName = titleName;
                this.channel = new ChannelItem();
                this.channel.setChannelId(channelId);
                this.channel.setChannelName(channelName);
            }

        }

    }

    public static class MessageTemplate {

        private static final Map<Long, MessageTemplateEnum> MESSAGE_TEMPLATE_MAP = new HashMap<>();

        private static final MessageTemplateEnum DEFAULT_MESSAGE_TEMPLATE = MessageTemplateEnum.MESSAGE;

        static {
            MESSAGE_TEMPLATE_MAP.put(6L, MessageTemplateEnum.LOCAL_BIG_BRAND);
            MESSAGE_TEMPLATE_MAP.put(3L, MessageTemplateEnum.RECRUIT);
        }

        /**
         * 根据频道id获取消息模板类型
         *
         * @param channelId 频道id
         * @return 消息模板类型
         */
        public static MessageTemplateEnum get(Long channelId) {
            return MESSAGE_TEMPLATE_MAP.getOrDefault(channelId, DEFAULT_MESSAGE_TEMPLATE);
        }

    }

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class ChannelItem implements Serializable {

        public static final ChannelItem NONE = new ChannelItem(0L, "无");

        /**
         * 频道id
         */
        private Long channelId;

        /**
         * 频道名称
         */
        private String channelName;

    }

}
